#include "frpguimainwindow.h"
#include "ui_frpguimainwindow.h"

#include <QDebug>
#include <QFileDialog>
#include <QProcess>
#include <QSettings>
#include <QTemporaryFile>
#include <QTimer>
#include <baseutil.h>



FrpGuiMainWindow::FrpGuiMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::FrpGuiMainWindow)
    , user_frps_service_loaded(false)
    , user_frpc_service_loaded(false)
{
    ui->setupUi(this);

    loadFrpProgramPath();
    loadFrpProgramConfig();

    action_frps = ui->menu_help->addAction("探索 frps 工具", this, &FrpGuiMainWindow::choose_frps_tool);
    action_frpc = ui->menu_help->addAction("探索 frpc 工具", this, &FrpGuiMainWindow::choose_frpc_tool);

    action_frps_text_update();
    action_frpc_text_update();

    connect(ui->text_frps, &QPlainTextEdit::textChanged, this, &FrpGuiMainWindow::frps_verify);
    connect(ui->text_frpc, &QPlainTextEdit::textChanged, this, &FrpGuiMainWindow::frpc_verify);

    if (ui->text_frps->toPlainText().isEmpty()) {
        ui->text_frps->setPlainText(frps_toml_template());
    }

    if (ui->text_frpc->toPlainText().isEmpty()) {
        ui->text_frpc->setPlainText(frpc_toml_template());
    }

    connect(ui->pb_frps, &QPushButton::clicked, this, &FrpGuiMainWindow::frps_apply);
    connect(ui->pb_frpc, &QPushButton::clicked, this, &FrpGuiMainWindow::frpc_apply);

    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "将 frp 服务配置路径写入到:"
             << settings.fileName();
    settings.setValue("service/frps", user_systemd_service_frps_path());
    settings.setValue("service/frpc", user_systemd_service_frpc_path());

    QTimer *frp_service_alive_checker = new QTimer(this);
    frp_service_alive_checker->setInterval(1000);
    connect(frp_service_alive_checker, &QTimer::timeout, this, &FrpGuiMainWindow::frp_service_alive_check);
    frp_service_alive_checker->start();

    QTimer *frp_service_load_checker = new QTimer(this);
    frp_service_load_checker->setInterval(5000);
    connect(frp_service_load_checker, &QTimer::timeout, this, &FrpGuiMainWindow::frp_service_load_check);
    frp_service_load_checker->start();

    frp_service_load_check();
}

FrpGuiMainWindow::~FrpGuiMainWindow()
{
    delete ui;
}

QString FrpGuiMainWindow::frps_toml_template()
{
    return R"(bindPort = 7000
)";
}

QString FrpGuiMainWindow::frpc_toml_template()
{
    return R"(serverAddr = "127.0.0.1"
serverPort = 7000

[[proxies]]
name = "test-tcp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
)";
}

QString FrpGuiMainWindow::configPath() const
{
    return BaseUtil::appConfigDir() + "frp.ini";
}

QString FrpGuiMainWindow::frpsConfigPath() const
{
    return BaseUtil::appConfigDir() + "frps.toml";
}

QString FrpGuiMainWindow::frpcConfigPath() const
{
    return BaseUtil::appConfigDir() + "frpc.toml";
}

QString FrpGuiMainWindow::user_systemd_service_dir() const
{
    QString path = BaseUtil::configDir() + "systemd/user";
    BaseUtil::mkdir(path);
    return path + QDir::separator();
}

void FrpGuiMainWindow::loadFrpProgramPath()
{
    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "从配置文件中读取 frps/frpc 程序路径:"
             << settings.fileName();

    frpsPath = settings.value("program/frps", "").toString();
    frpcPath = settings.value("program/frpc", "").toString();

    qDebug() << "frps 程序位置:"
             << frpsPath << ((frpsPath.isEmpty()) ? "(未设置)" : "(已设置)");
    qDebug() << "frpc 程序位置:"
             << frpcPath << ((frpcPath.isEmpty()) ? "(未设置)" : "(已设置)");

    if(!QFile(frpsPath).exists()) {
        frpsPath.clear();
    }
    if(!QFile(frpcPath).exists()) {
        frpcPath.clear();
    }
}

void FrpGuiMainWindow::loadFrpProgramConfig()
{
    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "从配置文件中读取 frps/frpc 程序配置:"
             << settings.fileName();

    frpsPath = settings.value("program/frps", "").toString();
    frpcPath = settings.value("program/frpc", "").toString();

    ui->text_frps->setPlainText(settings.value("config/frps", "").toString());
    ui->text_frpc->setPlainText(settings.value("config/frpc", "").toString());

    frps_status(ui->text_frps->toPlainText().isEmpty() == false);
    frpc_status(ui->text_frpc->toPlainText().isEmpty() == false);

    ui->cb_frps->setChecked(settings.value("state/frps", user_systemd_service_isActive("frps.service")).toBool());
    ui->cb_frpc->setChecked(settings.value("state/frpc", user_systemd_service_isActive("frpc.service")).toBool());
}

void FrpGuiMainWindow::choose_frps_tool()
{
    QString path = QFileDialog::getOpenFileName(nullptr, "选择你的 frps 程序", "", "frps");
    if (!path.isEmpty()) {
        frpsPath = path;
        QSettings settings(configPath(), QSettings::IniFormat);
        qDebug() << "将 frps 程序路径写入到:"
                 << settings.fileName();
        settings.setValue("program/frps", frpsPath);
        action_frps_text_update();
    }
}

void FrpGuiMainWindow::choose_frpc_tool()
{
    QString path = QFileDialog::getOpenFileName(nullptr, "选择你的 frpc 程序", "", "frpc");
    if (!path.isEmpty()) {
        frpcPath = path;
        QSettings settings(configPath(), QSettings::IniFormat);
        qDebug() << "将 frpc 程序路径写入到:"
                 << settings.fileName();
        settings.setValue("program/frpc", frpcPath);
        action_frpc_text_update();
    }
}

void FrpGuiMainWindow::action_frps_text_update()
{
    if (!frpsPath.isEmpty()) {
        action_frps->setText("修改 frps 工具");
    } else {
        action_frps->setText("探索 frps 工具");
    }
    ui->gb_frps->setEnabled(!frpsPath.isEmpty());
}

void FrpGuiMainWindow::action_frpc_text_update()
{
    if (!frpcPath.isEmpty()) {
        action_frpc->setText("修改 frpc 工具");
    } else {
        action_frpc->setText("探索 frpc 工具");
    }
    ui->gb_frpc->setEnabled(!frpcPath.isEmpty());
}

void FrpGuiMainWindow::frps_verify()
{
    if (!frpsPath.isEmpty()) {
        bool verify = frp_verify(frpsPath, ui->text_frps->toPlainText());
        frps_status(verify);
        if (verify) {
            QSettings settings(configPath(), QSettings::IniFormat);
            qDebug() << "将 frps 配置写入到:"
                     << settings.fileName();
            settings.setValue("config/frps", ui->text_frps->toPlainText());
        }
    }
}

void FrpGuiMainWindow::frpc_verify()
{
    if (!frpcPath.isEmpty()) {
        bool verify = frp_verify(frpcPath, ui->text_frpc->toPlainText());
        frpc_status(verify);
        if (verify) {
            QSettings settings(configPath(), QSettings::IniFormat);
            qDebug() << "将 frpc 配置写入到:"
                     << settings.fileName();
            settings.setValue("config/frpc", ui->text_frpc->toPlainText());
        }
    }
}

void FrpGuiMainWindow::frps_status(bool verify)
{
    ui->status_frps->setText(verify ? "有效" : "异常");
    ui->status_frps->setStyleSheet(verify ? "color: green" : "color: red");
    ui->pb_frps->setEnabled(verify);
}

void FrpGuiMainWindow::frpc_status(bool verify)
{
    ui->status_frpc->setText(verify ? "有效" : "异常");
    ui->status_frpc->setStyleSheet(verify ? "color: green" : "color: red");
    ui->pb_frpc->setEnabled(verify);
}

void FrpGuiMainWindow::frps_apply()
{
    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "从配置文件中读取 frps 程序配置:"
             << settings.fileName();

    QFile frps_toml(frpsConfigPath());
    if (frps_toml.open(QIODevice::WriteOnly)) {
        frps_toml.write(settings.value("config/frps", "").toString().toUtf8());
        frps_toml.close();
    }

    QFile frps_service(user_systemd_service_frps_path());
    if (frps_service.open(QIODevice::WriteOnly)) {
        frps_service.write(frp_systemd_service_unit("Frps", frpsPath, frpsConfigPath()).toUtf8());
        frps_service.close();
    }

    if (ui->cb_frps->isChecked()) {
//        user_systemd_daemon_reload();
//        user_systemd_service_restart("frps.service");
        ui->statusbar->showMessage("应用: 配置保存，Frps 服务准备重启");
    } else {
//        user_systemd_daemon_reload();
//        user_systemd_service_stop("frps.service");
        ui->statusbar->showMessage("应用: 配置保存，Frps 服务已关闭");
    }
    user_systemd_daemon_reload();
    user_systemd_service_stop("frps.service");
//    frp_service_load_check();
//    frp_service_alive_check();
}

void FrpGuiMainWindow::frpc_apply()
{
    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "从配置文件中读取 frpc 程序配置:"
             << settings.fileName();

    QFile frpc_toml(frpcConfigPath());
    if (frpc_toml.open(QIODevice::WriteOnly)) {
        frpc_toml.write(settings.value("config/frpc", "").toString().toUtf8());
        frpc_toml.close();
    }

    QFile frpc_service(user_systemd_service_frpc_path());
    if (frpc_service.open(QIODevice::WriteOnly)) {
        frpc_service.write(frp_systemd_service_unit("Frpc", frpcPath, frpcConfigPath()).toUtf8());
        frpc_service.close();
    }

    if (ui->cb_frpc->isChecked()) {
//        user_systemd_daemon_reload();
//        user_systemd_service_restart("frpc.service");
        ui->statusbar->showMessage("应用: 配置保存，Frpc 服务准备重启");
    } else {
//        user_systemd_daemon_reload();
//        user_systemd_service_stop("frpc.service");
        ui->statusbar->showMessage("应用: 配置保存，Frpc 服务已关闭");
    }

    user_systemd_daemon_reload();
    user_systemd_service_stop("frpc.service");
//    frp_service_load_check();
//    frp_service_alive_check();
}

void FrpGuiMainWindow::frp_service_alive_check()
{
    static bool startup_state;
    bool frps_alive_state = user_systemd_service_isActive("frps.service");
    bool frpc_alive_state = user_systemd_service_isActive("frpc.service");

    if (!startup_state) {
        startup_state = true;
//        ui->cb_frps->setChecked(frps_alive_state);
//        ui->cb_frpc->setChecked(frpc_alive_state);
        connect(ui->cb_frps, &QCheckBox::stateChanged, this, &FrpGuiMainWindow::frps_state_changed);
        connect(ui->cb_frpc, &QCheckBox::stateChanged, this, &FrpGuiMainWindow::frpc_state_changed);
    }

    ui->service_frps->setStyleSheet(QString("color: %1").arg(user_frps_service_loaded ? frps_alive_state?"green":"black" : "pink"));
    ui->service_text_frps->setText(user_frps_service_loaded?frps_alive_state?"运行中":"已停止":"未配置");

    ui->service_frpc->setStyleSheet(QString("color: %1").arg(user_frpc_service_loaded ? frpc_alive_state?"green":"black" : "pink"));
    ui->service_text_frpc->setText(user_frpc_service_loaded?frpc_alive_state?"运行中":"已停止":"未配置");

    if (user_frps_service_loaded) {
        frps_service_startup(frps_alive_state);
    }

    if (user_frpc_service_loaded) {
        frpc_service_startup(frpc_alive_state);
    }
    // ui->statusbar->showMessage(QString("服务状态: frps 服务%1, frpc 服务%2").arg((frps_alive_state?"运行中":"已停止")).arg((frpc_alive_state?"运行中":"已停止")));
}

void FrpGuiMainWindow::frps_service_startup(bool alive)
{
    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "从配置文件中读取 frps 服务状态设置:"
             << settings.fileName();

    if (!alive && settings.value("state/frps").toBool()) {
        user_systemd_service_start("frps.service");
        qDebug() << "尝试启动 frps 服务.";
        ui->service_frps->setStyleSheet(QString("color: %1").arg("yellow"));
        ui->service_text_frps->setText("启动中");
    }

    if (alive && !settings.value("state/frps").toBool()) {
        user_systemd_service_stop("frps.service");
        qDebug() << "尝试关闭 frps 服务.";
        ui->service_frps->setStyleSheet(QString("color: %1").arg("gray"));
        ui->service_text_frps->setText("停止中");
    }
}

void FrpGuiMainWindow::frpc_service_startup(bool alive)
{
    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "从配置文件中读取 frpc 服务状态设置:"
             << settings.fileName();

    if (!alive && settings.value("state/frpc").toBool()) {
        user_systemd_service_start("frpc.service");
        qDebug() << "尝试启动 frpc 服务.";
        ui->service_frpc->setStyleSheet(QString("color: %1").arg("yellow"));
        ui->service_text_frpc->setText("启动中");
    }

    if (alive && !settings.value("state/frpc").toBool()) {
        user_systemd_service_stop("frpc.service");
        qDebug() << "尝试关闭 frpc 服务.";
        ui->service_frpc->setStyleSheet(QString("color: %1").arg("gray"));
        ui->service_text_frpc->setText("停止中");
    }
}

void FrpGuiMainWindow::frp_service_load_check()
{
    user_frps_service_loaded = user_systemd_service_show("frps.service", "LoadState", "loaded");
    user_frpc_service_loaded = user_systemd_service_show("frpc.service", "LoadState", "loaded");
}

void FrpGuiMainWindow::frps_state_changed(int state)
{
    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "将 frps 状态写入到:"
             << settings.fileName();
    settings.setValue("state/frps", state == Qt::CheckState::Checked);
}

void FrpGuiMainWindow::frpc_state_changed(int state)
{
    QSettings settings(configPath(), QSettings::IniFormat);
    qDebug() << "将 frpc 状态写入到:"
             << settings.fileName();
    settings.setValue("state/frpc", state == Qt::CheckState::Checked);
}

bool FrpGuiMainWindow::frp_verify(const QString &program, const QString &config)
{
    bool verify = false;

    QTemporaryFile temporaryFile;
    if (temporaryFile.open()) {
        temporaryFile.write(config.toUtf8());
        temporaryFile.flush();
        QProcess frpVerify;
        frpVerify.start(program, QStringList() << "verify" << "-c" << temporaryFile.fileName());
        frpVerify.waitForFinished();
        verify = (frpVerify.exitCode() == 0);
    } else {
        qDebug() << "无法创建 frp 临时文件";
    }

    return verify;
}

QString FrpGuiMainWindow::frp_systemd_service_unit(const QString &unit, const QString &programPath, const QString &configPath)
{
    return frp_systemd_service_unit_template().arg(unit).arg(programPath).arg(configPath);
}

QString FrpGuiMainWindow::frp_systemd_service_unit_template()
{
    return R"(
# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: LGPL-3.0-or-later

[Unit]
Description=%1 Service

[Service]
Type=simple
ExecStart=%2 -c %3
Restart=always
)";
}

void FrpGuiMainWindow::user_systemd_daemon_reload()
{
    QProcess daemon_reload;
    daemon_reload.start("systemctl", QStringList() << "--user" << "daemon-reload");
    daemon_reload.waitForFinished();
}

bool FrpGuiMainWindow::user_systemd_service_show(const QString &service, const QString &attribute, const QString &value)
{
    QProcess show_service;
    show_service.start("systemctl", QStringList() << "--user" << "show" << service);
    show_service.waitForFinished();
    QString data = show_service.readAllStandardOutput();
    auto lines = data.split("\n", Qt::SkipEmptyParts);
    foreach (auto line, lines) {
        if (line.startsWith(QString("%1=").arg(attribute))) {
            return line.endsWith(value);
        }
    }
    return false;
}

bool FrpGuiMainWindow::user_systemd_service_isActive(const QString &service)
{
    QProcess is_active_service;
    is_active_service.start("systemctl", QStringList() << "--user" << "is-active" << service);
    is_active_service.waitForFinished();
    return is_active_service.readAllStandardOutput().startsWith("active");
}

void FrpGuiMainWindow::user_systemd_service_stop(const QString &service)
{
    QProcess restart_service;
    restart_service.start("systemctl", QStringList() << "--user" << "stop" << service);
    restart_service.waitForFinished();
}

void FrpGuiMainWindow::user_systemd_service_start(const QString &service)
{
    QProcess restart_service;
    restart_service.start("systemctl", QStringList() << "--user" << "start" << service);
    restart_service.waitForFinished();
}
